AWS S3兼容文档¶
支持的SDK¶
- Java SDK
- GO SDK
- Python SDK
- PHP SDK
支持的接口¶
Bucket
- List Buckets
- Put Bucket
- Put Bucket Acl
- Get Bucket Acl
- Delete Bucket
- Get Bucket Location
Object
- Put Object
- Put Object Copy
- Get Object
- Delete Object
- Delete Multiple Objects
- Head Object
- List Objects
Multipart Upload
- Initiate Multipart Upload
- Upload Part
- List Parts
- List Multipart Uploads
- Complete Multipart Upload
- Abort Multipart Upload
约束说明¶
参数 | 详细说明 |
---|---|
加密 | 暂不支持 |
Acl | 支持public-read,private |
Grant | 不支持 |
Lifecycle | 不支持 |
多版本 | 不支持 |
Region | 支持us-east-1对应的分区为杭州 |
StorageClass | 默认为STANDARD,其他的存储级别暂不支持 |
Authorization | 支持v4,v2,目前只支持在header加入签名信息,暂不支持url签名 |
MFA授权 | 不支持 |
Bucket接口¶
List Buckets¶
兼容说明¶
接口和S3兼容
代码示例¶
Java:
AWSCredentials credentials= new BasicAWSCredentials("ak","sk");
AmazonS3 s3Client = new AmazonS3Client(credentials);
s3Client.setEndpoint("http://xxx.com");//指定为nos的endpoint
List<Bucket> listBuckets = s3Client.listBuckets();
for(Bucket bucket : listBuckets){
System.out.println(bucket.getOwner() + "-->" + bucket.getName() + "-->" + bucket.getCreationDate());
}
Get Bucket Acl¶
兼容说明¶
- 因为NOS的权限不能赋给其他的用户,所以返回的Body中只有一条记录
- 在返回值中,Permission的取值有两种类型,Read(public-read),Write(private)
代码示例¶
Java:
AccessControlList accessControlList = s3Client.getBucketAcl(bucketName);
System.out.println("owner : " + accessControlList.getOwner().getId() + " : " + accessControlList.getOwner().getDisplayName());
for(Grant grant : accessControlList.getGrantsAsList()){//由于不支持授权给其他用户,所以List中只存在一个Grant
System.out.println(grant.getGrantee().getIdentifier() + " : " + grant.getPermission() + " : " + grant.getGrantee().getTypeIdentifier());
}
Object接口¶
Put Object¶
兼容说明¶
- x-amz-tagging 不支持
- x-amz-website-redirect-location 不支持
- Expires 不支持
- Content-Encoding 不支持
- Java SDK不支持http上传
代码示例¶
Java:
String content = "test put object content";
String testKey = "testKey";
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,testKey,"/");
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(content.length());
Map<String,String> userMeta = new TreeMap<>();
userMeta.put("userMeta1","meta1");
userMeta.put("userMeta2","meta2");
objectMetadata.setUserMetadata(userMeta);
putObjectRequest.setMetadata(objectMetadata);
putObjectRequest.setInputStream(new ByteInputStream(content.getBytes(Charset.forName("UTF-8")),content.getBytes(Charset.forName("UTF-8")).length));
s3Client.putObject(putObjectRequest);
Put Object Copy¶
兼容说明¶
- x-amz-metadata-directive,不支持设置,用户原信息会复制过去
- x-amz-copy-xxx 等参数不支持
- x-amz-storage-class,存储级别使用默认(STANDARD)的就好,NOS不支持其他的存储级别
- x-amz-tagging-directive,x-amz-website-redirect-location 也不支持
代码示例¶
Java:
CopyObjectResult copyObjectResult = s3Client.copyObject(srcBucket,srcKey,destBucket,destKey);
System.out.println(copyObjectResult.getETag());
System.out.println(copyObjectResult.getLastModifiedDate());
Get Object¶
兼容说明¶
- NOS不支持的操作,相关的响应头是不会返回的
- If-Unmodified-Since,If-Match,If-None-Match 不支持
代码示例¶
Java:
String testKey = "testKey";
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName,testKey);
S3Object s3Object = s3Client.getObject(getObjectRequest);
System.out.println(s3Object.getObjectMetadata().getContentLength());
if(s3Object != null){
S3ObjectInputStream s3ObjectInputStream = s3Object.getObjectContent();
byte[] buf = new byte[1024];
int readLen;
try {
while((readLen = s3ObjectInputStream.read(buf)) > -1){
System.out.println(new String(buf,0,readLen));
}
System.out.println(s3Object.getObjectMetadata().getUserMetadata());
} catch (IOException e) {
e.printStackTrace();
}
}
Delete Multiple Objects¶
兼容说明¶
接口和S3兼容
代码示例¶
Java:
String testBucketName = bucketName;
String testKey = "test";
for(int i = 0;i < 5;++i){
s3Client.putObject(testBucketName,testKey + i,"test" + i);
}
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(testBucketName);
List<DeleteObjectsRequest.KeyVersion> list = new LinkedList<>();
for(int i = 0; i < 3;++i){
list.add(new DeleteObjectsRequest.KeyVersion(testKey + i));
}
deleteObjectsRequest.setKeys(list);
deleteObjectsRequest.setQuiet(true);
DeleteObjectsResult deleteObjectsResult = s3Client.deleteObjects(deleteObjectsRequest);
for(DeleteObjectsResult.DeletedObject deleteObject : deleteObjectsResult.getDeletedObjects()){
System.out.println(deleteObject.getKey());
}
Head Object¶
兼容说明¶
- 和GetObject一样,也不支持If-Unmodified-Since,If-Match,If-None-Match参数
- 同样的,加密也不支持
- 返回中带有Object该有的信息
代码示例¶
Java:
ObjectMetadata objectMetadata = s3Client.getObjectMetadata(bucketName,testKey);
System.out.println(objectMetadata.getUserMetadata());
System.out.println(objectMetadata.getContentLength());
System.out.println(objectMetadata.getETag());
List Objects¶
兼容说明¶
S3的List Objects有两个版本(v1,v2),NOS目前只兼容v1
代码示例¶
Java:
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName("sdktest-private");
List<S3ObjectSummary> listResult = new ArrayList<>();
ObjectListing listObjects = s3Client.listObjects(listObjectsRequest);
do {
listResult.addAll(listObjects.getObjectSummaries());
if (listObjects.isTruncated()) {
ListObjectsRequest request = new ListObjectsRequest();
request.setBucketName(listObjectsRequest.getBucketName());
request.setMarker(listObjects.getNextMarker());
listObjects = s3Client.listObjects(request);
} else {
break;
}
} while (listObjects != null);
Multipart Upload接口¶
Initiate Multipart Upload¶
兼容说明¶
x-amz-website-redirect-location,不支持
代码示例¶
Java:
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(
bucketName, key);
InitiateMultipartUploadResult initResponse =
s3Client.initiateMultipartUpload(initRequest);
Upload Part¶
兼容说明¶
接口和S3兼容
代码示例¶
Java:
UploadPartRequest uploadRequest = new UploadPartRequest()
.withBucketName(bucketName).withKey(key)
.withUploadId(initResponse.getUploadId()).withPartNumber(i)
.withFileOffset(filePosition)
.withFile(file)
.withPartSize(partSize);
s3Client.uploadPart(uploadRequest)
List Parts¶
兼容说明¶
- 对于s3中的encoding头,如果包含了,也不处理
- 因为nos没有生命周期的概念,所以响应中不会加入lifecycle相关的响应头
代码示例¶
Java:
ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName,key,initResponse.getUploadId());
//initResponse通过上面的init方式获取
s3Client.listParts(listPartsRequest);
List Multipart Uploads¶
兼容说明¶
- request只支持max-uploads,key-marker参数
- response中,因为不支持有的请求参数,所以有的元素也不会返回,详细见下表:
resp header | S3 | NOS |
---|---|---|
UploadIdMarker | √ | x |
NextUploadIdMarker | √ | x |
Encoding-Type | √ | x |
Initiator | √ | x |
CommonPrefixes | √ | x |
CommonPrefixes.Prefix | √ | x |
代码示例¶
Java:
ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
listMultipartUploadsRequest.setMaxUploads(2);
MultipartUploadListing multipartUploadListing = s3Client.listMultipartUploads(listMultipartUploadsRequest);
System.out.println("bucketName : " + multipartUploadListing.getBucketName());
System.out.println(multipartUploadListing.getMaxUploads());
for(MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()){
System.out.println(multipartUpload.getInitiated() + " : " + multipartUpload.getUploadId() + " : " +
multipartUpload.getStorageClass());
}
Complete Multipart Upload¶
兼容说明¶
除了版本控制和加密,NOS完全兼容S3
代码示例¶
Java:
CompleteMultipartUploadRequest compRequest = new
CompleteMultipartUploadRequest(bucketName,
key,
initResponse.getUploadId(),//为initiateMultipartUpload的返回值
partETags); //partEtags通过上述ListParts构造
Abort Multipart Upload¶
兼容说明¶
接口和S3兼容
代码示例¶
Java:
s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(
bucketName, key, initResponse.getUploadId()));//initResponse为initiateMultipartUpload的返回值
完整的分块上传示例¶
Java:
List<PartETag> partETags = new ArrayList<>();
// Step 1: Initialize.
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(
bucketName, key);
InitiateMultipartUploadResult initResponse =
s3Client.initiateMultipartUpload(initRequest);
File file = new File(filePath);
long contentLength = file.length();
long partSize = 5 * 1024 * 1024; // Set part size to 5 MB.
try {
// Step 2: Upload parts.
long filePosition = 0;
for (int i = 1; filePosition < contentLength; i++) {
// Last part can be less than 5 MB. Adjust part size.
partSize = Math.min(partSize, (contentLength - filePosition));
// Create request to upload a part.
UploadPartRequest uploadRequest = new UploadPartRequest()
.withBucketName(bucketName).withKey(key)
.withUploadId(initResponse.getUploadId()).withPartNumber(i)
.withFileOffset(filePosition)
.withFile(file)
.withPartSize(partSize);
// Upload part and add response to our list.
partETags.add(s3Client.uploadPart(uploadRequest).getPartETag());
ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName,key,initResponse.getUploadId());
s3Client.listParts(listPartsRequest);
filePosition += partSize;
}
// Step 3: Complete.
CompleteMultipartUploadRequest compRequest = new
CompleteMultipartUploadRequest(bucketName,
key,
initResponse.getUploadId(),
partETags);
s3Client.completeMultipartUpload(compRequest);
} catch (Exception e) {
//error,abort
s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(
bucketName, key, initResponse.getUploadId()));
}